home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
forms
/
FORMS
/
draw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
19KB
|
654 lines
/*
* draw.c
*
* This file is part of the basis of the Forms Library
*
* It contains lowlevel routines to draw boxes, text, etc. These routines
* are used by the object drawing routines for objects.
*
* Written by Mark Overmars
*
* Version 2.2 a
* Date: Jun 21, 1993
*/
#include <malloc.h>
#include <stdio.h>
#include "gl/gl.h"
#include "gl/device.h"
#include "fmclient.h"
#include <string.h>
#include "forms.h"
/*********
Mouse stuff.
*********/
void fl_get_mouse(float *xx,float *yy)
/* returns the position of the mouse in world coordinates*/
{
long x,y;
getorigin(&x,&y);
*xx = (float) (getvaluator(MOUSEX)-x);
*yy = (float) (getvaluator(MOUSEY)-y);
}
/*********
Clipping.
*********/
void fl_set_clipping(float x,float y,float w,float h)
/* Sets the clipping region */
{
Screencoord sl,sr,sb,st;
sl = (short) (x);
sr = (short) (sl + w - 1.0);
sb = (short) (y);
st = (short) (sb + h - 1.0);
scrmask(sl,sr,sb,st);
}
void fl_unset_clipping()
/* Resets the clipping region */
{
Screencoord sl,sr,sb,st;
getviewport(&sl,&sr,&sb,&st);
scrmask(sl,sr,sb,st);
}
/*********
Font related stuff
*********/
typedef struct {
int defined; /* Whether the font is defined */
char name[64]; /* Name of the font */
int fnumb; /* Number of sizes in use */
float size[32]; /* different sizes in use */
fmfonthandle fhandle[32]; /* handles for different sizes */
} FL_FONT;
static FL_FONT fl_font[FL_MAXFONT]; /* The fonts used */
static fmfonthandle use_font(int numb, float size)
/* Returns the handle to font numb in the required size. */
{
int i;
/* Error checking */
if (numb < 0 || numb >= FL_MAXFONT)
{
fl_error("use_font","Trying to use non-existing font");
return use_font(0,FL_NORMAL_FONT);
}
if (!fl_font[numb].defined)
{
fl_error("use_font","Trying to use undefined font");
return use_font(0,FL_NORMAL_FONT);
}
/* Create basic font if required */
if (fl_font[numb].fnumb == 0)
{
fl_font[numb].fhandle[0] = fmfindfont(fl_font[numb].name);
/* Check whether existing */
if (fl_font[numb].fhandle[0] == NULL)
fl_font[numb].fhandle[0] = fmfindfont(fl_font[0].name);
fl_font[numb].fnumb = 1;
}
/* Search for the required size. */
for (i=1; i<fl_font[numb].fnumb; i++)
if (size == fl_font[numb].size[i])
return fl_font[numb].fhandle[i];
/* If not available, create it */
if (fl_font[numb].fnumb == 32)
{
fmfreefont(fl_font[numb].fhandle[31]);
fl_font[numb].fnumb--;
}
fl_font[numb].size[fl_font[numb].fnumb] = size;
fl_font[numb].fhandle[fl_font[numb].fnumb] =
fmscalefont(fl_font[numb].fhandle[0],size);
fl_font[numb].fnumb++;
return fl_font[numb].fhandle[fl_font[numb].fnumb-1];
}
void fl_set_font_name(int numb, char name[])
/* Sets the name of a particular font number. */
{
int i;
if (numb < 0 || numb >= FL_MAXFONT)
{
fl_error("fl_set_font_name","Setting name of non-existing font number.");
return;
}
if (fl_font[numb].defined)
for (i=0; i < fl_font[numb].fnumb; i++)
fmfreefont(fl_font[numb].fhandle[i]);
fl_font[numb].defined = TRUE;
strcpy(fl_font[numb].name,name);
fl_font[numb].fnumb = 0;
}
void fl_set_font(char normalname[], char boldname[],
char italicname[], char fixedname[])
/* Old style setting routine. WILL BE REMOVED IN THE FUTURE. */
{
fl_set_font_name(0,normalname);
fl_set_font_name(1,boldname);
fl_set_font_name(2,italicname);
fl_set_font_name(3,fixedname);
}
void fl_init_fonts()
/* Initializes the fonts being used to the defaults */
{
int i;
for (i=0; i<FL_MAXFONT;i++) fl_font[i].defined = FALSE;
fminit();
fl_set_font_name(0,FL_FONT_NAME_0);
fl_set_font_name(1,FL_FONT_NAME_1);
fl_set_font_name(2,FL_FONT_NAME_2);
fl_set_font_name(3,FL_FONT_NAME_3);
fl_set_font_name(4,FL_FONT_NAME_4);
fl_set_font_name(5,FL_FONT_NAME_5);
fl_set_font_name(6,FL_FONT_NAME_6);
fl_set_font_name(7,FL_FONT_NAME_7);
fl_set_font_name(8,FL_FONT_NAME_8);
fl_set_font_name(9,FL_FONT_NAME_9);
fl_set_font_name(10,FL_FONT_NAME_10);
fl_set_font_name(11,FL_FONT_NAME_11);
fl_set_font_name(12,FL_FONT_NAME_12);
fl_set_font_name(13,FL_FONT_NAME_13);
fl_set_font_name(14,FL_FONT_NAME_14);
fl_set_font_name(15,FL_FONT_NAME_15);
}
float fl_get_char_height(float size, int style)
/* returns the height of the current font in size points */
{
fmfontinfo info;
fmfonthandle fnt = use_font(style,size);
if (fnt == NULL) return 0.0;
fmgetfontinfo(fnt,&info);
return (float) info.height;
}
float fl_get_string_width(float size, int style, char str[])
/* returns the width of the given string */
{
fmfontinfo info;
fmfonthandle fnt = use_font(style,size);
if (fnt == NULL) return 0.0;
fmgetfontinfo(fnt,&info);
return (float) fmgetstrwidth(fnt,str);
}
float fl_get_char_width(float size, int style, char ch)
/* returns the width of the given character */
{
char str[2];
str[0] = ch; str[1] = '\0';
return fl_get_string_width(size,style,str);
}
/*********
Color Stuff.
*********/
static short fl_red[4096], fl_green[4096], fl_blue[4096];
void fl_init_colormap()
{
long cmwin;
int i;
/* Read colormap colors into internal table */
fl_save_user_window();
noport();
cmwin = winopen("CM");
for (i=0; i<4096; i++)
{fl_red[i] = 0; fl_green[i] = 0; fl_blue[i] = 0; }
for (i=0; i<256; i++)
getmcolor(i,&fl_red[i],&fl_green[i],&fl_blue[i]);
winclose(cmwin);
fl_restore_user_window();
/* Correct colors for small number of bitplanes */
if (getgdesc(GD_BITS_NORM_DBL_RED) <= 4)
for (i=0; i<256; i++)
{
fl_red[i] = 8 * (fl_red[i] / 8);
fl_green[i] = 8 * (fl_green[i] / 8);
fl_blue[i] = 8 * (fl_blue[i] / 8);
}
}
void fl_color(int col)
/* Sets a colormap index in RGB mode. */
{
if (fl_rgbmode)
RGBcolor(fl_red[col],fl_green[col],fl_blue[col]);
else
color(col);
}
void fl_mapcolor(int i, short red, short green, short blue)
/* Changes a colormap index */
{
if (fl_rgbmode)
{ fl_red[i] = red; fl_green[i] = green; fl_blue[i] = blue;}
else
mapcolor(i,red,green,blue);
}
void fl_getmcolor(int i, short *red, short *green, short *blue)
/* Returns a colormap index */
{
if (fl_rgbmode)
{*red = fl_red[i]; *green = fl_green[i]; *blue = fl_blue[i];}
else
getmcolor(i,red,green,blue);
}
/*********
Drawing boxes.
*********/
static void vv(float x,float y)
{ short v[2] ; v[0] = (short) x; v[1] = (short) y; v2s(v);}
void fl_line(float x, float y, float w, float h, int col)
/* Draws a line in the given color. */
{
fl_color(col);
bgnline(); vv(x,y); vv(x+w-1.0,y+h-1.0); endline();
}
void fl_rect(float x, float y, float w, float h, int col)
/* Draws a rectangle in the given color. */
{
fl_color(col);
bgnpolygon();
vv(x,y); vv(x+w,y); vv(x+w,y+h); vv(x,y+h);
endpolygon();
}
void fl_bound(float x, float y, float w, float h, int col)
/* Draws a boundary in the given color. */
{
fl_color(col);
bgnclosedline();
vv(x,y); vv(x+w-1.,y); vv(x+w-1.,y+h-1.); vv(x,y+h-1.);
endclosedline();
}
void fl_rectbound(float x, float y, float w, float h, int col)
/* Draws a rectangle in the given color with a black boundary. */
{
fl_color(col);
bgnpolygon();
vv(x+1.,y+1.); vv(x+w-1.,y+1.); vv(x+w-1.,y+h-1.); vv(x+1.,y+h-1.);
endpolygon();
fl_color(0);
bgnclosedline();
vv(x,y); vv(x+w-1.,y); vv(x+w-1.,y+h-1.); vv(x,y+h-1.);
endclosedline();
}
#define RN 5
#define RS 15.0
static float offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
static void rbox(int fill, float x,float y,float w,float h)
/* Draws a rounded box */
{
int i;
float rsx ,rsy, rs;
rsx = 0.4*w; rsy = 0.4*h;
if (rsx > rsy) rs = rsy; else rs = rsx;
if (rs > RS) rs = RS;
rsx = rs; rsy = rs;
if (fill) bgnpolygon(); else bgnclosedline();
for (i=0; i<RN; i++)
vv(x + offset[RN-i-1]*rsx, y + offset[i] * rsy);
for (i=0; i<RN; i++)
vv(x + offset[i]*rsx, y + h-1.0 - offset[RN-i-1] * rsy);
for (i=0; i<RN; i++)
vv(x + w-1.0 - offset[RN-i-1]*rsx, y + h-1.0 - offset[i] * rsy);
for (i=0; i<RN; i++)
vv(x + w-1.0 - offset[i]*rsx, y + offset[RN-i-1] * rsy);
if (fill) endpolygon(); else endclosedline();
}
void fl_drw_box(int style,float x,float y,float w,float h,int c,float bw)
/* Draws a box. */
{
if (style == FL_NO_BOX) return;
switch (style)
{
case FL_ROUNDED_BOX:
fl_color(c); rbox(1,x,y,w,h);
fl_color(0); rbox(0,x,y,w,h);
break;
case FL_RFLAT_BOX:
fl_color(c); rbox(1,x,y,w,h);
break;
case FL_RSHADOW_BOX:
/* draw the shadow */
fl_color(FL_RIGHT_BOUND_COL);
fl_set_clipping(x+bw,y-bw,w,bw+2.0);
rbox(1,x+bw,y-bw,w,h);
fl_set_clipping(x+w-1.0,y,bw+1.0,h-bw);
rbox(1,x+bw,y-bw,w,h);
fl_set_clipping(x+w+bw-RS,y,RS,RS);
rbox(1,x+bw,y-bw,w,h);
fl_unset_clipping();
/* draw the box */
fl_color(c); rbox(1,x,y,w,h);
fl_color(0); rbox(0,x,y,w,h);
break;
case FL_FRAME_BOX:
fl_rect(x+2.,y+2.,w-4.,h-4.,c);
fl_bound(x+1.,y,w-1.,h-1.,FL_LEFT_BOUND_COL);
fl_color(FL_RIGHT_BOUND_COL);
bgnline(); vv(x,y); vv(x,y+h-1.); vv(x+w-1.,y+h-1.); endline();
bgnline(); vv(x+2.,y+1.);vv(x+w-2.,y+1.);vv(x+w-2.,y+h-3.); endline();
break;
case FL_BORDER_BOX:
fl_rectbound(x,y,w,h,c); break;
case FL_FLAT_BOX:
fl_rect(x,y,w,h,c); break;
case FL_SHADOW_BOX:
fl_rect(x+bw,y-bw,w,bw,FL_RIGHT_BOUND_COL);
fl_rect(x+w,y-bw,bw,h,FL_RIGHT_BOUND_COL);
fl_rectbound(x,y,w,h,c);
break;
case FL_UP_BOX:
fl_rect(x+bw+1.,y+bw+1.,w-2*bw-2.,h-2*bw-2.,c);
fl_rect(x+1.,y+h-bw-1.,w-2.,bw,FL_TOP_BOUND_COL);
fl_rect(x+1.,y+1.,w-2.,bw,FL_BOT_BOUND_COL);
fl_color(FL_RIGHT_BOUND_COL);
bgnpolygon();
vv(x+w-bw-1.,y+bw+1.); vv(x+w-bw-1.,y+h-bw-1.);
vv(x+w-1.,y+h-1.); vv(x+w-1.,y+1.);
endpolygon();
fl_color(FL_LEFT_BOUND_COL);
bgnpolygon();
vv(x+1.,y+1.); vv(x+1.,y+h-1.);
vv(x+bw+1.,y+h-bw-1.); vv(x+bw+1.,y+bw+1.);
endpolygon();
fl_bound(x,y,w,h,0);
break;
case FL_DOWN_BOX:
fl_rectbound(x+bw,y+bw,w-2*bw,h-2*bw,c);
fl_rect(x,y+h-bw,w,bw,FL_BOT_BOUND_COL);
fl_rect(x,y,w,bw,FL_TOP_BOUND_COL);
fl_color(FL_LEFT_BOUND_COL);
bgnpolygon();
vv(x+w-bw,y+bw); vv(x+w-bw,y+h-bw); vv(x+w,y+h); vv(x+w,y);
endpolygon();
fl_color(FL_RIGHT_BOUND_COL);
bgnpolygon();
vv(x,y); vv(x,y+h); vv(x+bw,y+h-bw); vv(x+bw,y+bw);
endpolygon();
break;
default:
fl_error("fl_draw_box","Unknown box type");
break;
}
}
/*********
Drawing text.
*********/
#define NL 10
/***
Major text drawing routine
***/
void fl_drw_string(
int horalign, /* Horizontal alignment -1=left, 0=center, 1=right */
int vertalign, /* Vertical alignment -1=bottom, 0=center, 1=top */
float x, float y, float w, float h, /* Bounding box */
int clip, /* Whether to clip to bounding box */
int backcol, /* Background color */
int forecol, /* Foreground color (text color) */
int curscol, /* Cursor color */
float size, /* Font size */
int style, /* Font style */
int curspos, /* The cursor position (-1 = no cursor) */
int selstart,int selend, /* The selected region (end<start = no region) */
char str[]) /* The (muli-line) string */
{
int i; /* counter */
char tc; /* temporary character */
float tt; /* temp value */
char *lines[1024]; /* pointers to the start of the different lines */
int start[1024]; /* start position of these lines */
float startx[1024]; /* start x-coordinate of these lines */
float starty[1024]; /* start y-coordinate of these lines */
float width[1024]; /* string width of the lines */
int lnumb; /* number of lines */
fmfonthandle fnt; /* font to be used */
fmfontinfo info; /* info of the font */
float height; /* height of the font */
float desc; /* descender of the font */
int slstart,slend; /* Temporary selection positions */
float xsel,wsel; /* position and width of selection area */
/* Check whether anything has to be done */
if (curspos != 0 && (str == NULL || str[0] == '\0')) return;
/* Set the font to be used and get some info */
fnt = use_font(style,size);
if (fnt == NULL) return;
fmsetfont(fnt);
fmgetfontinfo(fnt,&info);
height = info.ysize;
desc = info.yorig;
/* Set clipping if required */
if (clip) fl_set_clipping(x,y,w,h);
/* Split string into lines */
lines[0] = &(str[0]);
start[0] = 0;
lnumb = 1;
for (i = 0; str[i] != '\0'; i++)
if (str[i] == NL)
{
str[i] = '\0';
lines[lnumb] = &(str[i+1]);
start[lnumb] = i+1;
lnumb++;
}
start[lnumb] = i+1;
/* Calculate start coordinates of lines */
for (i = 0; i < lnumb; i++)
{
width[i] = fmgetstrwidth(fnt,lines[i]);
if (horalign == -1) startx[i] = x;
if (horalign == 0) startx[i] = x + 0.5*(w-width[i]);
if (horalign == 1) startx[i] = x + w - width[i];
if (vertalign == -1) starty[i] = y - (i - lnumb)*height;
if (vertalign == 0) starty[i] = y + 0.5*h - (i - 0.5*lnumb)*height;
if (vertalign == 1) starty[i] = y + h - i*height;
}
/* Draw the lines */
for (i = 0; i < lnumb; i++)
{
/* Check whether visible */
if (clip && starty[i]-height > y+h) continue;
if (clip && starty[i] < y) break;
/* Draw it */
cmov2(startx[i],starty[i]-height+desc);
fl_color(forecol);
fmprstr(lines[i]);
/* Draw selection area if required. */
if (selstart < start[i+1] && selend >start[i])
{
if (selstart <= start[i]) slstart = start[i]; else slstart = selstart;
if (selend >= start[i+1]) slend = start[i+1]-1; else slend = selend;
tc = str[slstart];
str[slstart] = '\0';
xsel = startx[i] + fmgetstrwidth(fnt,lines[i]);
str[slstart] = tc;
tc = str[slend];
str[slend] = '\0';
wsel = fmgetstrwidth(fnt,&(str[slstart]));
fl_rect(xsel,starty[i]-height,wsel,height,forecol);
cmov2(xsel,starty[i]-height+desc);
fl_color(backcol);
fmprstr(&(str[slstart]));
str[slend] = tc;
}
}
/* Draw the cursor */
if (curspos >= 0)
{
i=0; while (start[i] <= curspos) i++;
i--;
tc = str[curspos];
str[curspos] = '\0';
tt = fmgetstrwidth(fnt,lines[i]);
str[curspos] = tc;
fl_rect(startx[i]+tt,starty[i]-height,2.,height,curscol);
}
/* Restore the original string. */
for (i = 1; i < lnumb; i++)
str[start[i]-1] = NL;
/* Reset clipping if required */
if (clip) fl_unset_clipping();
}
/***
Next routine returns the position of the mouse in a string
***/
int fl_get_pos_in_string(
int horalign, /* Horizontal alignment -1=left, 0=center, 1=right */
int vertalign, /* Vertical alignment -1=bottom, 0=center, 1=top */
float x, float y, float w, float h, /* Bounding box */
float size, /* Font size */
int style, /* Font style */
float xpos, float ypos, /* Position of the mouse */
char str[]) /* The (muli-line) string */
{
int i; /* counter */
char tc; /* temporary character */
int start[1024]; /* start position of the lines */
int lnumb; /* number of lines */
int theline; /* number of line in which the mouse lies */
char *line; /* line in which mouse lies */
float startx; /* start x-coordinate of this line */
float width; /* string width of this line */
fmfonthandle fnt; /* font to be used */
fmfontinfo info; /* info of the font */
float height; /* height of the font */
float toppos; /* y-coord of the top line */
/* Check whether anything has to be done */
if (str == NULL || str[0] == '\0') return 0;
/* Set the font to be used and get some info */
fnt = use_font(style,size);
if (fnt == NULL) return 0;
fmsetfont(fnt);
fmgetfontinfo(fnt,&info);
height = info.ysize;
/* Split string into lines */
start[0] = 0;
lnumb = 1;
for (i = 0; str[i] != '\0'; i++)
if (str[i] == NL) start[lnumb++] = i+1;
start[lnumb] = i+1;
/* Calculate line in which mouse lies */
if (vertalign == -1) toppos = y - lnumb*height;
if (vertalign == 0) toppos = y + 0.5*h + 0.5*lnumb*height;
if (vertalign == 1) toppos = y + h;
theline = (int) ((toppos - ypos)/height);
if (theline < 0) return 0;
if (theline >= lnumb) return strlen(str);
line = &(str[start[theline]]);
/* Calculate start coordinate of the line */
tc = str[start[theline+1]-1];
str[start[theline+1]-1] = '\0';
width = fmgetstrwidth(fnt,line);
if (horalign == -1) startx = x;
if (horalign == 0) startx = x + 0.5*(w-width);
if (horalign == 1) startx = x + w - width;
str[start[theline+1]-1] = tc;
for (i = start[theline]+1; i < start[theline+1]; i++)
{
tc = str[i];
str[i] = '\0';
if (xpos-startx <= fmgetstrwidth(fnt,line)) { str[i] = tc; return i-1;}
str[i] = tc;
}
return start[theline+1]-1;
}
/***
Misselaneous text drawing routines
***/
void fl_drw_text_cursor(int align,float x,float y,float w,float h,
int c,float size,int style,char str[],int cc,int pos)
/* Draws a (multi-line) text with a cursor. */
{
int horalign,vertalign;
float height = fl_get_char_height(size,style);
switch (align) {
case FL_ALIGN_LEFT: horalign = -1; vertalign = 0; break;
case FL_ALIGN_RIGHT: horalign = 1; vertalign = 0; break;
case FL_ALIGN_CENTER: horalign = 0; vertalign = 0; break;
case FL_ALIGN_TOP: horalign = 0; vertalign = 1; break;
case FL_ALIGN_BOTTOM: horalign = 0; vertalign = -1; break;
}
fl_drw_string(horalign,vertalign,
x+0.5*height,y+0.25*height,w-height,h-0.5*height,
FALSE,
7,c,cc,
size,style,
pos,
0,-1,
str);
}
void fl_drw_text(int align,float x,float y,float w,float h,
int c,float size,int style,char str[])
/* Draws a text inside a box. */
{
if (str == NULL || str[0] == '\0') return;
if (str[0] == '@') if (fl_draw_symbol(str,x,y,w,h,c)) return;
fl_drw_text_cursor(align,x,y,w,h,c,size,style,str,0,-1);
}
void fl_drw_text_beside(int align,float x,float y,float w,float h,
int c,float size,int style, char str[])
/* Draws a text besides a box. */
{
if (str == NULL || str[0] == '\0') return;
if (align == FL_ALIGN_LEFT)
fl_drw_text(FL_ALIGN_RIGHT,x-h,y,h,h,c,size,style,str);
else if (align == FL_ALIGN_RIGHT)
fl_drw_text(FL_ALIGN_LEFT,x+w,y,h,h,c,size,style,str);
else if (align == FL_ALIGN_TOP)
fl_drw_text(FL_ALIGN_BOTTOM,x,y+h,w,h,c,size,style,str);
else if (align == FL_ALIGN_BOTTOM)
fl_drw_text(FL_ALIGN_TOP,x,y-h,w,h,c,size,style,str);
else
fl_drw_text(FL_ALIGN_CENTER,x,y,w,h,c,size,style,str);
}